package loadcount

import (
	"database/sql"
	"fmt"
	"time"

	"gitee.com/smewl13/learn/utils"
	_ "github.com/go-sql-driver/mysql"
)

type DBConnect struct {
	DBUrl   string
	DB      *sql.DB
	rolling Rolling
	merage  Merage
}

type Rolling struct {
	Time      string `db:"time"`
	HostName  string `db:"host"`
	TableName string `db:"tablename"`
	Receive   int64  `db:"receive"`
	Processed int64  `db:"processed"`
	Success   int64  `db:"success"`
	Failed    int64  `db:"failed"`
}

type Merage struct {
	Time      string `db:"time"`
	HostName  string `db:"host"`
	TableName string `db:"tablename"`
	RecordNum int64  `db:"recordnum"`
	Failed    int64  `db:"failed"`
}

func ConnectDB(conf *utils.Mysql) *DBConnect {
	db := DBConnect{
		DBUrl: fmt.Sprintf("%s:%s@%s(%s:%d)/%s",
			conf.User,
			conf.Passwd,
			conf.Protocol,
			conf.Host,
			conf.Port,
			conf.DBname),
	}
	var err error
	db.DB, err = sql.Open("mysql", db.DBUrl)
	if err != nil {
		utils.Error.Fatalf("Mysql连接失败: %s\n", err)
	}
	db.DB.SetConnMaxLifetime(time.Second * 100)
	db.DB.SetMaxOpenConns(100)
	db.DB.SetMaxIdleConns(16)
	return &db
}

func (db *DBConnect) DbOperator(sql string) {
	result, err := db.DB.Exec(sql)
	if err != nil {
		utils.Error.Fatalf("sql(%s)执行: %v\n", sql, err)
		return
	}
	rowsaffected, err := result.RowsAffected()
	if err != nil {
		utils.Error.Printf("获取RowsAffected失败: %v\n", err)
		return
	}
	utils.Info.Printf("RowsAffected: %v\n", rowsaffected)
}

func (db *DBConnect) InsertRolling(rolling *Rolling) {
	insertRolling, _ := db.DB.Prepare("insert into rolling values(?,?,?,?,?,?,?)")
	defer insertRolling.Close()
	_, err := insertRolling.Exec(
		&rolling.Time,
		&rolling.HostName,
		&rolling.TableName,
		&rolling.Receive,
		&rolling.Processed,
		&rolling.Success,
		&rolling.Failed,
	)
	if err != nil {
		utils.Error.Printf("rolling表插入数据失败: %s\n", err)
	}
}

func (db *DBConnect) InsertMerage(merage *Merage) {
	insertRolling, _ := db.DB.Prepare("insert into merage values(?,?,?,?,?)")
	defer insertRolling.Close()
	_, err := insertRolling.Exec(
		&merage.Time,
		&merage.HostName,
		&merage.TableName,
		&merage.RecordNum,
		&merage.Failed,
	)
	if err != nil {
		utils.Error.Printf("rolling表插入数据失败: %s\n", err)
	}
}

func (db *DBConnect) RollingQuery(startTime string, endTime string) map[string]map[int]int64 {
	result := make(map[string]map[int]int64)
	querySql, _ := db.DB.Prepare("select * from rolling where time >= ? and time <= ?")
	queryResult, err := querySql.Query(startTime, endTime)
	if err != nil {
		utils.Error.Printf("rolling表查询失败: %s\n", err)
		return result
	}
	defer queryResult.Close()
	for i := 0; queryResult.Next(); i++ {
		queryResult.Scan(
			&db.rolling.Time,
			&db.rolling.HostName,
			&db.rolling.TableName,
			&db.rolling.Receive,
			&db.rolling.Processed,
			&db.rolling.Success,
			&db.rolling.Failed,
		)

		nonFlag := 0
		for key := range result {
			if db.rolling.TableName == key {
				nonFlag = 1
				break
			}
		}
		if nonFlag == 0 {
			result[db.rolling.TableName] = map[int]int64{0: 0, 1: 0, 2: 0, 3: 0}
		}

		result[db.rolling.TableName][0] += db.rolling.Receive
		result[db.rolling.TableName][1] += db.rolling.Processed
		result[db.rolling.TableName][2] += db.rolling.Success
		result[db.rolling.TableName][3] += db.rolling.Failed
	}
	return result
}

func (db *DBConnect)MerageQuery(startTime string, endTime string) map[string]map[int]int64{
	result := make(map[string]map[int]int64)
	querySql,_ := db.DB.Prepare("select * from merage where time >= ? and time <= ?")
	queryResult, err := querySql.Query(startTime, endTime)
	if err != nil {
		utils.Error.Printf("rolling表查询失败: %s\n", err)
		return result
	}
	defer queryResult.Close()
	for i:=0;queryResult.Next();i++{
		queryResult.Scan(
			&db.merage.Time,
			&db.merage.HostName,
			&db.merage.TableName,
			&db.merage.RecordNum,
			&db.merage.Failed,
		)

		nonFlag := 0
		for key := range result{
			if key == db.merage.TableName{
				nonFlag=1
				break
			}
		}
		if nonFlag == 0{
			result[db.merage.TableName]=map[int]int64{0:0,1:0}
		}

		result[db.merage.TableName][0] += db.merage.RecordNum
		result[db.merage.TableName][1] += db.merage.Failed
	}
	return result
}
